home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 4 / The 640 Meg Shareware Studio CD-ROM Volume IV (Data Express)(1994).ISO / clang / fhprtsc.zip / NHPRTSC.ASM < prev    next >
Assembly Source File  |  1993-05-01  |  12KB  |  394 lines

  1.     PAGE    ,132
  2.     TITLE    HPRTSC
  3.     SUBTTL    Description
  4.  
  5. ; Revision by Bill Reynolds, 10.12.89 
  6. ; Revised version fixes bug which caused the printer to 
  7. ; linefeed incorrectly, resulting in poor printed image, also
  8. ; have (optionally) commented out the code which prompts for
  9. ; which screen page to print, thus causing the program to dump
  10. ; graphics page 1 when PrtSc is pressed and board is in graphics
  11. ; mode. If you would like this function back, just uncomment the
  12. ; lines that are marked X below, and delete the one extra line
  13. ; that has been added.
  14.  
  15. ; Copyright (c) 1987, Background Processes
  16. ;
  17. ; Permission is hereby granted to copy, distribute, modify, include,
  18. ; burn, rape, or pillage this software in accordance with the following
  19. ; guidelines:
  20. ;
  21. ;    1) Distribution of this program is to be free. If a charge is made
  22. ;       for copying, it must be no more than $5 US. Permission for
  23. ;       inclusion into commercial products must be obtained individually.
  24. ;
  25. ;    2) Distribution of the program must include this complete source
  26. ;       code, or at least it should be made available. Software
  27. ;       exchange should not only be a way of getting free software,
  28. ;       but should also be a learning experience. The best way to
  29. ;       learn is to be able to read the source code.
  30. ;
  31. ;    3) You promise not to laugh at the code (at least not too hard). I'm
  32. ;       a PDP-11 programmer. If that doesn't mean anything to you, ask
  33. ;       a hacker friend about the advantages of orthogonal instruction sets
  34. ;       and REAL general registers.
  35. ;
  36. ;    4) If you find (or correct - hint, hint) any bugs in this program, I
  37. ;       would appreciate it if you would let me know. This way I can
  38. ;       learn, too.
  39. ;
  40. ; Alan Groupe
  41. ; Background Processes
  42. ; PO Box 6347
  43. ; Nashua, NH 03063-6347
  44.  
  45. ; This program implements a graphics screen dump from a Hercules
  46. ; monochrome graphics board. It is similar to the DOS GRAPHICS.COM in
  47. ; that it takes over the PrtSc interrupt.
  48.  
  49. ; When HPRTSC is typed at the DOS prompt, it grabs the PrtSc interrupt
  50. ; vector, and then issues a terminate and stay resident DOS function
  51. ; call. When the PrtSc key is pressed, this program checks the Hercules
  52. ; board to determine whether it is in text or graphics mode. If the
  53. ; board is in text mode, the program simply executes a far jump to the
  54. ; original PrtSc routine. If the board is in graphics mode, the program
  55. ; waits for a key to be pressed on the keyboard. If the '1' key is pressed,
  56. ; the program scans through the first graphics page (B0000 - B7FFF; called
  57. ; page 0 in the Hercules manual) and formats it for output on the printer.
  58. ; If the '2' key is pressed, the second graphics page (B8000 - BFFFF) is
  59. ; printed. If any other key is pressed, you will hear a short beep and HPRTSC
  60. ; will just return. You can use this to freeze an animated graphics display
  61. ; to look at it more closely. Just press PrtSc to freeze the screen. To
  62. ; unfreeze it, just press any key other than '1' or '2'.
  63. ; The dot mapping of a Hercules board is a little weird. Each byte in
  64. ; the graphics memory corresponds to eight dots horizontally, with the
  65. ; most significant bit of each byte representing the leftmost dot of the
  66. ; eight. There are 720 dots across on the display, so the first 90 bytes
  67. ; (B0000 - B005A) make up the first line on the screen (line 1).
  68. ; However, the next 90 bytes are not line 2, but rather line 5. The next
  69. ; 90 bytes, line 9. This continues down the screen until line 345
  70. ; (B1E3C). The remaining 170 bytes (B1E96 - B1FFF) are unused. Then the
  71. ; 90 byte groups starting at B2000 correspond to lines 2, 6, 10, etc.
  72. ; Therefore, lines 1-10 have the respective starting addresses B0000,
  73. ; B2000, B4000, B6000, B005A, B205A, B405A, B605A, B00B4, and B20B4.
  74. ; This, of course, is not even close to how an Epson printer maps dots
  75. ; on the paper. The Epson printer takes an eight bit byte and prints a
  76. ; column of 8 dots vertically, with the most significant bit at the top.
  77. ; Since the Hercules board is organized horizontally and the Epson printer
  78. ; is organized vertically, this program prints the screen image rotated 90
  79. ; degrees.
  80.  
  81.     SUBTTL    Entry Point
  82.     PAGE    +
  83.  
  84. cseg    segment
  85.     assume    cs:cseg,ds:cseg
  86.  
  87. ; This is the initial program entry point. It jumps to 'init' which sets
  88. ; up the interrupt vector, prints out a message confirming program load,
  89. ; and does a terminate and stay resident call.
  90.  
  91.     jmp    init    ; jump around real code to load in memory
  92.     SUBTTL    PrtSc Entry Point
  93.     PAGE    +
  94.  
  95. ; This is the entry point when PrtSc is pressed. It is ORG'ed at location
  96. ; 348 (minus 100h) to allow the previous 348 bytes, including the now
  97. ; unnecessary PSP to be used as a buffer to hold a full vertical scan of the
  98. ; screen. 
  99.  
  100.     org    348-100h
  101.  
  102. int5:
  103.     push    ax
  104.     push    bx
  105.     push    dx
  106.  
  107. ; First we must determine whether the Hercules board is in text mode or
  108. ; graphics mode. This is done with a program given to me by Hercules Computer
  109. ; Technology Inc. It isn't real clear to me why this program works the way it
  110. ; does, but it appears that if you force trip the light pen, it returns the
  111. ; character location (6845 meaning) just past the end of the screen. This may
  112. ; have something to do with the fact that there is no light pen receiving a
  113. ; raster pulse. If this is the case, I have no idea if this still works if you
  114. ; actually have a light pen connected.
  115.  
  116. ourstat    equ    03bah
  117. notvsync equ    80h
  118. lpreset    equ    03bbh
  119. lpset    equ    03b9h
  120. our6845    equ    03b4h
  121. threshold equ    (80*25 + 45*87)/2
  122.  
  123.     mov    dx,ourstat
  124.  
  125. w1:    in    al,dx        ; first, wait for vertical retrace
  126.     test    al,notvsync
  127.     jz    w1
  128.  
  129. w2:    in    al,dx        ; then make sure not to test during vertical
  130.     test    al,notvsync    ; retrace
  131.     jnz    w2
  132.  
  133.     xor    al,al        ; tickle light pen
  134.     mov    dx,lpreset
  135.     out    dx,al
  136.     mov    dx,lpset
  137.     out    dx,al
  138.  
  139.     mov    al,16        ; get high byte of lp trip offset
  140.     mov    dx,our6845
  141.     out    dx,al
  142.     inc    dx
  143.     in    al,dx
  144.     mov    bh,al
  145.  
  146.     mov    al,17        ; and low byte
  147.     mov    dx,our6845
  148.     out    dx,al
  149.     inc    dx
  150.     in    al,dx
  151.  
  152.     mov    ah,bh        ; return light pen trip address
  153.     cmp    ax,threshold
  154.     pop    dx        ; restore original user registers
  155.     pop    bx
  156.     pop    ax
  157.     ja    gprint        ; above threshold, in graphics mode
  158.  
  159. ; The following two lines are a 'jmp far' instruction to jump to the BIOS
  160. ; print screen routine if the Hercules board is in text mode. The location
  161. ; is filled in in the 'init' routine.
  162.  
  163. tjump:    db    0eah        ;! JMP FAR 0:0
  164.     dw    0,0
  165.  
  166.     SUBTTL    Graphics Entry Point
  167.     PAGE    +
  168.  
  169. ; This is the entry point if the Hercules board is in graphics mode.
  170.  
  171. gprint:
  172.     push    ax        ; save all registers
  173.     push    bx
  174.     push    cx
  175.     push    dx
  176.     push    si
  177.     push    di
  178.     push    bp
  179.     push    ds
  180.     push    es
  181.  
  182. ; First test location 50:0 to see if print screen is already in progress.
  183.  
  184.     mov    ax,50h
  185.     mov    ds,ax
  186.     cmp    byte ptr ds:0,1    ; prtsc already active?
  187.     mov    byte ptr ds:0,1    ; it is now
  188.     mov    ax,cs        ; retore ds:
  189.     mov    ds,ax
  190.     jnz    gp1        ; print screen in progress before? no.
  191.     jmp    exit        ; yes
  192.  
  193. ; (B.R. Fix) Uncomment the lines marked 'X' below and delete the
  194. ; indicated instruction to restore page selection capability
  195. gp1:
  196. ;X    xor    ax,ax        ; set for read char
  197. ;X    int    16h        ; read char from keyboard
  198.     mov    dx,0b000h    ; assume page 1
  199. ;X    cmp    al,'1'
  200. ;X    je    gp3
  201.  
  202. ; (B.R. Fix) Delete this next line to restore the paging function
  203.     jmp    gp3
  204.  
  205. ;X    mov    dx,0b800h    ; page 2
  206. ;X    cmp    al,'2'
  207. ;X    je    gp3
  208. ;X
  209. ; neither '1' nor '2', so beep an error and return
  210. ;X
  211. ;Xtimer    equ    40h
  212. ;Xport_b    equ    61h
  213. ;X
  214. ;X    mov    al,10110110b    ; sel tim 2,lsb,msb,binary
  215. ;X    out    timer+3,al    ; write the timer mode reg
  216. ;X    mov    ax,533h        ; divisor for 1000 hz
  217. ;X    out    timer+2,al    ; write timer 2 cnt - lsb
  218. ;X    mov    al,ah
  219. ;X    out    timer+2,al    ; write timer 2 cnt - msb
  220. ;X    in    al,port_b    ; get current setting of port
  221. ;X    mov    ah,al        ; save that setting
  222. ;X    or    al,03        ; turn speaker on
  223. ;X    out    port_b,al
  224. ;X    sub    cx,cx        ; set count to 500 ms
  225. ;Xgp2:    loop    gp2        ; delay before turning off
  226. ;X    mov    al,ah        ; recover value of port
  227. ;X    out    port_b,al
  228.     jmp    done    
  229.  
  230. ;
  231. ; set up printer for graphics printing
  232. ;
  233. gp3:    mov    ds,dx        ; segment address of page requested
  234.     push    cs        ; es points to work area which is at
  235.     pop    es        ;  beginning of code segment
  236.     xor    dx,dx        ; printer number is zero (LPT1)
  237.     xor    si,si        ; horizontal offset (start at left edge)
  238.  
  239.     mov    ax,27        ; select 8/72" line feeds (ESC A 8)
  240.     int    17h
  241.     mov    ax,'A'
  242.     int    17h
  243.     mov    ax,8
  244.     int    17h
  245.  
  246. ;(B.R. Fix) BUG! These lines set the printer back to normal line feeds,
  247. ;undoing the work done in the last block. 
  248. ;    mov    ax,27        ; set selection in force (ESC 2)
  249. ;    int    17h
  250. ;    mov    ax,'2'
  251. ;    int    17h
  252.  
  253. ; start running through screen starting with lower left corner, working up
  254. ; and then to the right
  255. ;
  256. ; l1 is loop for each vertical pass. This is also one print line.
  257.  
  258. l1:    mov    bx,1e3ch    ; bottom-most scan line in first quadrant
  259.     mov    cx,87        ; # horizontal lines in a quadrant (348/4)
  260.        xor    di,di        ; pointer into ES: work area (beginning of code)
  261.  
  262. l2:    mov    al,6000h[bx+si]    ; get character from quadrant 4 scan line
  263.     stosb            ; and store in work area
  264.     cmp    al,0        ; if it was other than a zero, store new
  265.     je    $+4        ; of di in dx so dx will be length of line to
  266.     mov    dx,di        ; print (null truncated)
  267.  
  268.     mov    al,4000h[bx+si]    ; do likewise for third quadrant
  269.     stosb
  270.     cmp    al,0
  271.     je    $+4
  272.     mov    dx,di
  273.  
  274.     mov    al,2000h[bx+si]    ; and second
  275.     stosb
  276.     cmp    al,0
  277.     je    $+4
  278.     mov    dx,di
  279.  
  280.     mov    al,[bx+si]    ; and the first quadrant
  281.     stosb
  282.     cmp    al,0
  283.     je    $+4
  284.     mov    dx,di
  285.  
  286.     sub    bx,5ah        ; up one horizontal scan line (90 bytes)
  287.     loop    l2        ;  (effectively 4 horizontal scan lines)
  288.  
  289.     cmp    dx,0        ; completely blank vertical line?
  290.     je    l5        ; don't print, just advance paper
  291.     push    dx        ; save length of line to print
  292.     xor    dx,dx        ; for printer zero, again
  293.     mov    cx,10        ; count for left margin (ie, 10 spaces)
  294. l3:    mov    ax,' '        ; the print them
  295.     int    17h
  296.     loop    l3
  297.     mov    ax,27        ; then print the graphics line
  298.     int    17h        
  299.     mov    ax,'L'        ; ESC L introduction (double density)
  300.     int    17h
  301.     pop    cx        ; length of line to print
  302.     shl    cx,1        ; *2 since we print double for double density
  303.     mov    ax,cx
  304.     xor    ah,ah        ; get least significant byte
  305.     int    17h        ; and send it
  306.     xor    ah,ah
  307.     mov    al,ch        ; then get most significant byte
  308.     int    17h        ; and send it
  309.     shr    cx,1        ; then shift back down to real count
  310.  
  311.     push    si        ; save horizontal offset
  312.     xor    si,si        ; point to save graphics line
  313. l4:    lods    byte ptr cs:0    ; get a character to print
  314.     xor    ah,ah
  315.     push    ax        ; BUG: my clone BIOS' int 17 stomps on AL
  316.     int    17h        ; and print it
  317.     pop    ax        ; restore due to my BIOS' bug
  318.     int    17h        ; print a second time for increased density
  319.     loop    l4        ; till end of line
  320.     pop    si        ; and restore horizontal offset for next pass
  321.  
  322. l5:    mov    ax,0dh        ; now do a CRLF
  323.     int    17h
  324.     mov    ax,0ah
  325.     int    17h
  326.     
  327.     inc    si        ; move one space to the right
  328.     cmp    si,5ah        ; already on right hand edge?
  329.     jae    l6        ; yes
  330.     jmp    l1        ; no, do another vertical pass
  331. l6:
  332.     
  333.     mov    ax,27        ; set the printer back to 6lpi
  334.     int    17h        ;  (even if it was at 8lpi)
  335.     mov    ax,'2'
  336.     int    17h
  337.     mov    ax,12        ; really 12/72 of an inch
  338.     int    17h
  339.  
  340. done:    mov    ax,50h
  341.     mov    ds,ax
  342.     mov    byte ptr ds:0,0    ; prtsc is now over
  343.  
  344. exit:
  345.     pop    es        ; restore all registers
  346.     pop    ds
  347.     pop    bp
  348.     pop    di
  349.     pop    si
  350.     pop    dx
  351.     pop    cx
  352.     pop    bx
  353.     pop    ax
  354.  
  355.     iret            ; and return to what user was doing
  356.     SUBTTL    Initial Entry Point (Setup)
  357.     PAGE    +
  358. ; This is the code executed the first time the program is invoked. It first
  359. ; builds a jump instruction at location 'tjump' that jumps to the BIOS print
  360. ; screen routine when the Hercules board is in text mode. Then it loads the
  361. ; print screen vector to point to the entry point and issues a terminate and
  362. ; stay resident call.
  363.  
  364. init:
  365.     mov    ax,ds:2ch
  366.     mov    es,ax        ; segment address of environment strings
  367.     mov    ah,49h        ; deallocate our copy of environment strings
  368.     int    21h
  369.     mov    ax,3505h        ; get address for normal print screen
  370.     int    21h
  371.     mov    ax,es
  372.     mov    word ptr tjump+103h,ax    ; store segment address in jmp instr.
  373.     mov    word ptr tjump+101h,bx    ; likewise with offset
  374.  
  375.     mov    dx,offset int5+100h
  376.     mov    ax,2505h        ; grab print screen interrupt vector
  377.     int    21h
  378.  
  379.     mov    dx,offset announce+100h
  380.     mov    ah,09h            ; print announcement
  381.     int    21h
  382.     mov    dx,offset init+100h    ; lock program in memory
  383.     int    27h
  384.  
  385. announce:
  386.     db    0dh,0ah,'HPrtSc - Graphics Screen Dump, Version 1.00',0dh,0ah
  387.     db    'Copyright (c) 1987, Background Processes',0dh,0ah,'$'
  388.  
  389. cseg    ends
  390.     end
  391.